//Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Security.Permissions;

namespace Eas.WebCrawler.Common.Threading {
    /// <summary>A <see cref="WaitHandle"/> which can be waited on and which will fire when a <see cref="EventHandler"/> compliant event (delegate) fires.</summary>
    /// <typeparam name="TArgs">A type of <see cref="EventArgs"/> which is used in the <see cref="EventHandler"/> that will be waited on.</typeparam>
    ///	<remarks>The generic version of this class works with the generic version of <see cref="EventHandler"/> while the non-generic version wotks with the non-generic <see cref="EventHandler"/>.</remarks>
    /// <example><![CDATA[
    ///     EventHandlerCompletionEvent<MouseEventArgs> waiter = new EventHandlerCompletionEvent<MouseEventArgs>();
    ///     myForm.OnMouseMove  += waiter.CreateEvenHandler();
    ///     myForm.WaitOne(); 
    /// ]]>
    /// </example>
    public class EventHandlerCompletionEvent<TArgs> : System.Threading.WaitHandle
        where TArgs : System.EventArgs {

        private System.Threading.ManualResetEvent _event = new System.Threading.ManualResetEvent(false);

        /// <summary>Constructs an <see cref="EventHandlerCompletionEvent"/>.</summary>
        public EventHandlerCompletionEvent()
            : base() {
            Reset();
        }

        /// <summary>Cleans up the object.</summary>
        /// <param name="explicitDisposing">Whether or not this class is being finalized.</param>
        protected override void Dispose(bool explicitDisposing) {
            base.Dispose(explicitDisposing);
            ((IDisposable)_event).Dispose();
        }

        ///<summary>Creates a delegate to be fired</summary>
        public EventHandler<TArgs> CreateEventHandler() {
            return new EventHandler<TArgs>(HandleEvent);
        }

        /// <summary>Closes this wait handle.</summary>
        public override void Close() {
            base.Close();
            _event.Close();
        }

        /// <summary>Resets the wait handle.</summary>
        public void Reset() {
            _event.Reset();
        }

        /// <summary>Sets the wait handle.</summary>
        public void Set() {
            _event.Set();
        }

        /// <summary>A native pointer to this handle.</summary>
        [Obsolete("This member is obsolete.  See WaitHandle.Handle for details.", false)]
        public override IntPtr Handle {
            get {
                return _event.Handle;
            }
            [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
            set {
                _event.Handle = value;
            }
        }

        /// <summary>Wait until the event is fired.</summary>
        /// <returns>Whether or not the Wait completed or timed out.</returns>
        public override bool WaitOne() {
            return _event.WaitOne();
        }

        /// <summary>Wait until the event is fired.</summary>
        /// <param name="exitContext">The exit context for the wait.</param>
        /// <param name="millisecondsTimeout">The timeout to wait before exiting if the event does not fire.</param>
        /// <returns>Whether or not the Wait completed or timed out.</returns>
        public override bool WaitOne(int millisecondsTimeout, bool exitContext) {
            return _event.WaitOne(millisecondsTimeout, exitContext);
        }

        /// <summary>Wait until the event is fired.</summary>
        /// <param name="exitContext">The exit context for the wait.</param>
        /// <param name="timeout">The timeout to wait before exiting if the event does not fire.</param>
        /// <returns>Whether or not the Wait completed or timed out.</returns>
        public override bool WaitOne(TimeSpan timeout, bool exitContext) {
            return _event.WaitOne(timeout, exitContext);
        }

        private void HandleEvent(object sender, TArgs argument) {
            _event.Set();
        }

    }

    /// <summary>A <see cref="WaitHandle"/> which can be waited on and which will fire when a <see cref="EventHandler"/> compliant event (delegate) fires.</summary>
    ///	<remarks>The generic version of this class works with the generic version of <see cref="EventHandler"/> while the non-generic version wotks with the non-generic <see cref="EventHandler"/>.</remarks>
    /// <example><![CDATA[
    ///     EventHandlerCompletionEvent<MouseEventArgs> waiter = new EventHandlerCompletionEvent<MouseEventArgs>();
    ///     myForm.OnMouseMove  += waiter.CreateEvenHandler();
    ///     myForm.WaitOne(); 
    /// ]]>
    /// </example>
    public class EventHandlerCompletionEvent : System.Threading.WaitHandle {

        private System.Threading.ManualResetEvent _event = new System.Threading.ManualResetEvent(false);

        /// <summary>Constructs an <see cref="EventHandlerCompletionEvent"/>.</summary>
        public EventHandlerCompletionEvent()
            : base() {
            Reset();
        }

        /// <summary>Cleans up the object.</summary>
        /// <param name="explicitDisposing">Whether or not this class is being finalized.</param>
        protected override void Dispose(bool explicitDisposing) {
            base.Dispose(explicitDisposing);
            ((IDisposable)_event).Dispose();
        }

        ///<summary>Creates a delegate to be fired</summary>
        public EventHandler CreateEventHandler() {
            return new EventHandler(HandleEvent);
        }

        /// <summary>Closes this wait handle.</summary>
        public override void Close() {
            base.Close();
            _event.Close();
        }

        /// <summary>Resets the wait handle.</summary>
        public void Reset() {
            _event.Reset();
        }

        /// <summary>Sets the wait handle.</summary>
        public void Set() {
            _event.Set();
        }

        /// <summary>A native pointer to this handle.</summary>
        [Obsolete("This member is obsolete.  See WaitHandle.Handle for details.", false)]
        public override IntPtr Handle {
            get {
                return _event.Handle;
            }
            [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
            set {
                _event.Handle = value;
            }
        }

        /// <summary>Wait until the event is fired.</summary>
        /// <returns>Whether or not the Wait completed or timed out.</returns>
        public override bool WaitOne() {
            return _event.WaitOne();
        }

        /// <summary>Wait until the event is fired.</summary>
        /// <param name="exitContext">The exit context for the wait.</param>
        /// <param name="millisecondsTimeout">The timeout to wait before exiting if the event does not fire.</param>
        /// <returns>Whether or not the Wait completed or timed out.</returns>
        public override bool WaitOne(int millisecondsTimeout, bool exitContext) {
            return _event.WaitOne(millisecondsTimeout, exitContext);
        }

        /// <summary>Wait until the event is fired.</summary>
        /// <param name="exitContext">The exit context for the wait.</param>
        /// <param name="timeout">The timeout to wait before exiting if the event does not fire.</param>
        /// <returns>Whether or not the Wait completed or timed out.</returns>
        public override bool WaitOne(TimeSpan timeout, bool exitContext) {
            return _event.WaitOne(timeout, exitContext);
        }

        private void HandleEvent(object sender, System.EventArgs argument) {
            _event.Set();
        }

    }

}
